<script setup lang="ts">
import { ColumnsType } from 'ant-design-vue/es/table';
import { h } from 'vue'
const antIcons: any = inject('antIcons')
import { OperLogPage, PageRes, UpdateOperLogRes, updateOperLog, deleteOperLog } from '@/api/log'
import { SysUser } from '@/interface/user';
import { message } from 'ant-design-vue';
import {
  CheckOutlined,
  CloseOutlined
} from '@ant-design/icons-vue'
import { Key } from 'ant-design-vue/es/table/interface';
import { SysOperLog } from '@/interface/log';
import dayjs, { Dayjs } from 'dayjs'
import { useGlobalStore } from '@/store/globalStore';

const columns: ColumnsType<any> = [
  {
    title: '模块标题',
    dataIndex: 'title',
    key: 'title',
    ellipsis: true,
  },
  {
    title: '操作人员',
    dataIndex: 'operName',
    key: 'operName',
  },
  {
    title: '业务类型',
    dataIndex: 'businessType',
    key: 'businessType',
  },
  {
    title: '方法名称',
    dataIndex: 'method',
    key: 'method',
    ellipsis: true,
  },
  {
    title: '请求方式',
    dataIndex: 'requestMethod',
    key: 'requestMethod',
  },
  {
    title: '操作类别',
    dataIndex: 'operatorType',
    key: 'operatorType',
  },
  {
    title: '部门名称',
    dataIndex: 'deptName',
    key: 'deptName',
  },
  {
    title: '请求URL',
    dataIndex: 'operUrl',
    key: 'operUrl',
  },
  {
    title: '主机地址',
    dataIndex: 'operIp',
    key: 'operIp',
  },
  {
    title: '操作时间',
    dataIndex: 'operTime',
    key: 'operTime',
  },
  {
    title: '请求参数',
    dataIndex: 'operParam',
    key: 'operParam',
    ellipsis: true,
  },
  {
    title: '返回参数',
    dataIndex: 'jsonResult',
    key: 'jsonResult',
    ellipsis: true,
  },
  {
    title: '状态',
    dataIndex: 'status',
    key: 'status',
  },
  {
    title: '操作',
    key: 'operation',
    fixed: 'right',
    width: 150,
  },
];

const globalStore = useGlobalStore()

const data = ref<SysUser[]>([])

const contentBoxRef = ref<HTMLElement>()
const currentPage = ref<number>(1);
const size = ref<number>(10);
const total = ref<number>(0);
const isLoading = ref<boolean>(false);
const editApiLoading = ref<boolean>(false);
const editPopShow = ref<boolean>(false);
const searchValue = ref('')

const currEditDate = ref<Dayjs>()
const currEditData = reactive<SysOperLog>({
  operId: -1,
  title: '',
  businessType: -1,
  method: '',
  requestMethod: '',
  operatorType: -1,
  operName: '',
  deptName: '',
  operUrl: '',
  operIp: '',
  operLocation: '',
  operParam: '',
  jsonResult: '',
  status: 0,
  errorMsg: '',
  operTime: '',
})

const getLogs = async (isSearch = false) => {
  isLoading.value = true;
  data.value = []
  if (isSearch) {
    pageChanged(1, size.value)
    return
  }
  try {
    const { data: res }: { data: PageRes } = await OperLogPage(currentPage.value, size.value, searchValue.value)
    currentPage.value = res.data.current
    size.value = res.data.size
    total.value = res.data.total
    //key用于选中操作
    data.value = res.data.records.map((item: any) => {
      item.key = item.infoId
      return item
    })
  } catch (error) {
    console.error(error);
  } finally {
    isLoading.value = false;
  }
}

const pageChanged = (page: number, pageSize: number) => {
  currentPage.value = page
  size.value = pageSize
  getLogs()
}

const reloadData = () => {
  getLogs()
}

const resetData = () => {
  searchValue.value = ''
  pageChanged(1, 10)
}

const deleteData = async (_e: MouseEvent, operId: number) => {
  return new Promise((resolve) => {
    deleteOperLog(operId.toString()).then(res => {
      if (res.data.code == 200) {
        message.success('删除成功')
        reloadData()
      } else {
        message.error(res.data.msg || '删除失败')
      }
      resolve(true)
    }).catch((_err) => {
      resolve(true)
    })
  });
}

const deleteBatchData = async () => {
  deleteOperLog(selectedRows.value.join(',')).then(res => {
    if (res.data.code == 200) {
      message.success('删除成功')
      selectedRows.value = []
    } else {
      message.error(res.data.msg || '删除失败')
    }
    getLogs()
  })
}

const handleEditOk = async () => {
  editApiLoading.value = true
  try {
    const { data: res }: { data: UpdateOperLogRes } = await updateOperLog({
      ...currEditData,
      operTime: currEditDate.value?.format('YYYY-MM-DD HH:mm:ss') || currEditData.operTime
    })
    if (res.code == 200) {
      message.success('更新成功')
      getLogs()
      editPopShow.value = false
    } else {
      message.error(res.msg || '更新失败')
    }
  } catch (error) {

  } finally {
    editApiLoading.value = false
  }
}

const editData = (data: any) => {
  editPopShow.value = true
  const { operId, title, businessType, method, requestMethod, operatorType, operName, deptName,
    operUrl, operIp, operLocation, operParam, jsonResult, status, errorMsg, operTime } = data
  currEditData.operId = operId
  currEditData.title = title
  currEditData.businessType = businessType
  currEditData.method = method
  currEditData.requestMethod = requestMethod
  currEditData.operatorType = operatorType
  currEditData.operName = operName
  currEditData.deptName = deptName
  currEditData.operUrl = operUrl
  currEditData.operIp = operIp
  currEditData.operLocation = operLocation
  currEditData.operParam = operParam
  currEditData.jsonResult = jsonResult
  currEditData.errorMsg = errorMsg
  currEditData.status = status
  currEditData.operTime = operTime
  currEditDate.value = dayjs(currEditData.operTime, 'YYYY-MM-DD HH:mm:dd')
}

const onFinishFailed = (errorInfo: any) => {
  console.log('Failed:', errorInfo);
};

//当前选中行
const selectedRows = ref<Key[]>([])
const onSelectChange = (selectedRowKeys: Key[]) => {
  selectedRows.value = selectedRowKeys;
};

const tableStyle = reactive<{
  width: number,
  height: number
}>({
  width: 300,
  height: 300
})

onMounted(() => {
  getLogs()
  tableStyle.height = contentBoxRef.value?.clientHeight as number - 200
  tableStyle.width = contentBoxRef.value?.clientWidth as number
})
</script>
<template>
  <div class="box-border relative w-full h-full p-3" ref="contentBoxRef" :style="{ width: globalStore.isMobile ? 'calc(100% - 60px)' : '100%' }">
    <a-row>
      <a-col :span="24">
        <a-space class="flex flex-wrap">
          <a-input placeholder="标题/操作人/类型/方式" class="w-[230px]" v-model:value="searchValue"
            @keydown.enter="getLogs(true)" />
          <a-button type="primary" class="flex items-center bg-primary-2" :icon="h(antIcons['SearchOutlined'])"
            @click="getLogs(true)" :loading="isLoading">查询</a-button>
          <a-button class="flex items-center" :icon="h(antIcons['ReloadOutlined'])" @click="resetData">重置</a-button>
          <a-button class="flex items-center justify-center" :icon="h(antIcons['ReloadOutlined'])" shape="circle"
            @click="reloadData"></a-button>
          <a-button type="primary" class="flex items-center" danger :icon="h(antIcons['CloseOutlined'])"
            :disabled="selectedRows.length == 0" @click="deleteBatchData">删除</a-button>
        </a-space>
      </a-col>
    </a-row>
    <!-- 表格 -->
    <div class="mt-3  h-fit max-h-[647px]">
      <a-table :columns="columns" :data-source="data" :pagination="false" :loading="isLoading"
        :scroll="{ y: tableStyle.height, x: globalStore.isMobile ? 'calc(100% + 800px)' : '100%' }"
        :row-selection="{ selectedRowKeys: selectedRows, onChange: onSelectChange }">
        <template #bodyCell="{ column, text }">
          <template v-if="column.dataIndex === 'businessType'">
            <p>{{ text == '1' ? '新增' : text == '2' ? '修改' : text == '3' ? '删除' : '其他' }}</p>
          </template>
          <template v-if="column.dataIndex === 'operatorType'">
            <p>{{ text == '1' ? '后台用户' : text == '2' ? '手机用户' : '其他' }}</p>
          </template>
          <template v-if="column.dataIndex === 'status'">
            <a-tag :color="text === 0 ? 'success' : 'error'">
              {{ text === 0 ? 'success' : 'error' }}
            </a-tag>
          </template>
          <template v-if="column.dataIndex === 'accessTime'">
            <p>{{ text }}</p>
          </template>
          <template v-if="column.key === 'operation'">
            <a-space>
              <a-button type="primary" class="flex items-center bg-primary-2" size="small"
                @click="editData(text)">编辑</a-button>
              <a-popconfirm :title="`确定删除操作人为${text.operName}的日志记录吗?`" ok-text="确认" cancel-text="取消"
                :okButtonProps="{ type: 'default' }" @confirm="deleteData($event, text.operId)">
                <a-button size="small" type="primary" danger class="flex items-center text-white ">删除</a-button>
              </a-popconfirm>
            </a-space>
          </template>
        </template>
      </a-table>
    </div>
    <div
      class="absolute bottom-0 left-0 right-0 p-3 mt-3 bg-white border-t-[1px] z-10 dark:bg-darkBg dark:border-gray-600">
      <a-pagination v-model:current="currentPage" v-model:page-size="size" :total="total"
        :show-total="total => `总共 ${total} 条`" show-size-changer @change="pageChanged" />
    </div>

    <a-modal v-model:open="editPopShow" title="修改操作日志" :footer="null">
      <a-form :model="currEditData" name="currEditData" @finish="handleEditOk" class="mt-5" place="left"
        @finishFailed="onFinishFailed" v-bind="{
        labelCol: { span: 4 },
        wrapperCol: { span: 24 },
      }">
        <a-form-item name="title" label="模块标题" :rules="[{ required: true }]">
          <a-input v-model:value="currEditData.title" />
        </a-form-item>
        <a-form-item name="businessType" label="业务类型" :rules="[{ required: false }]">
          <a-input v-model:value="currEditData.businessType" />
        </a-form-item>
        <a-form-item name="method" label="方法名称" :rules="[{ required: false }]">
          <a-input v-model:value="currEditData.method" />
        </a-form-item>
        <a-form-item name="requestMethod" label="请求方式" :rules="[{ required: false }]">
          <a-input v-model:value="currEditData.requestMethod" />
        </a-form-item>
        <a-form-item name="operatorType" label="操作类别" :rules="[{ required: false }]">
          <a-input v-model:value="currEditData.operatorType" />
        </a-form-item>
        <a-form-item name="operName" label="操作人员" :rules="[{ required: false }]">
          <a-input v-model:value="currEditData.operName" />
        </a-form-item>
        <a-form-item name="deptName" label="部门名称" :rules="[{ required: false }]">
          <a-input v-model:value="currEditData.deptName" />
        </a-form-item>
        <a-form-item name="operUrl" label="请求URL" :rules="[{ required: false }]">
          <a-input v-model:value="currEditData.operUrl" />
        </a-form-item>
        <a-form-item name="operIp" label="主机地址" :rules="[{ required: false }]">
          <a-input v-model:value="currEditData.operIp" />
        </a-form-item>
        <a-form-item name="operLocation" label="操作地点" :rules="[{ required: false }]">
          <a-input v-model:value="currEditData.operLocation" />
        </a-form-item>
        <a-form-item name="operParam" label="请求参数" :rules="[{ required: false }]">
          <a-input v-model:value="currEditData.operParam" />
        </a-form-item>
        <a-form-item name="jsonResult" label="返回参数" :rules="[{ required: false }]">
          <a-input v-model:value="currEditData.jsonResult" />
        </a-form-item>
        <a-form-item name="status" label="状态" :rules="[{ required: false }]">
          <a-switch v-model:checked="currEditData.status" :checkedValue="0" :unCheckedValue="1">
            <template #checkedChildren>
              <CheckOutlined />
            </template>
            <template #unCheckedChildren>
              <CloseOutlined />
            </template>
          </a-switch>
        </a-form-item>
        <a-form-item name="operTime" label="登录日期" :rules="[{ required: false }]">
          <!-- <a-input v-model:value="currEditData.accessTime" /> -->
          <a-date-picker v-model:value="currEditDate" format="YYYY-MM-DD HH:mm:ss" show-time />
        </a-form-item>
        <a-form-item :wrapper-col="{
        offset: 17,
        span: 7
      }">
          <a-space>
            <a-button key="back" @click="editPopShow = false">取消</a-button>
            <a-button html-type="submit" type="primary" class="bg-primary-2" :loading="editApiLoading">修改</a-button>
          </a-space>
        </a-form-item>
      </a-form>
    </a-modal>
  </div>
</template>

<style scoped></style>